/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package deti.es.persistence.account;

import deti.es.ukni.persistence.entity.Account;
import deti.es.ukni.persistence.entity.Band;
import java.util.Date;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.*;

/**
 * Account Manager DAO
 * <br/>
 * Implementation of the {@link AccountManagerRemote} interface.
 *
 * @author ukni
 */
@Stateless( mappedName="ejb/MyBandAccountManager" )
public class AccountManagerBean implements AccountManagerRemote {

    @PersistenceContext
    private EntityManager manager;

    public AccountManagerBean() { }

    /**
     * Check user password against the password
     * stored in the database.
     *
     * @param Username  The name of the user
     * @param passwd    The password to check
     * 
     * @return An Account object if the password checks, null otherwise.
     *
     * @throws AccountDoesNotExist when the username does not exist.
     * @throws WrongPassword when the passords does not checks.
     */
    public Account login( String Username, String passwd ) throws AccountDoesNotExist, WrongPassword {

        Query q = manager.createQuery("SELECT a FROM Account a WHERE a.username = :username");
        q.setParameter("username", Username);

        try{
            Account acc = (Account) q.getSingleResult();

            if ( acc.getPassword().equals(passwd) )
                return acc;
            else
                throw new WrongPassword();

        } catch( NoResultException e ){
            throw new AccountDoesNotExist( Username );
        }
            
    }

    /**
     * Search for an account that matches the given id.
     *
     * @param IDAccount The id of the account.
     * @return An Account object that matches <code>IDAccount</code>,
     *         null otherwise.
     */
    public Account findAccount(Integer IDAccount ){
        try{
            Account acc = manager.find(Account.class, IDAccount);
            return acc;
        } catch( NoResultException e){

        }
        return null;
    }

    /**
     * Implementation of {@link AccountManagerRemote#createAccount}
     */
    public Account createAccount(String username, String email,
                                 String password, Integer accountType) {


        Account newAccount = new Account();

        newAccount.setUsername(username);
        newAccount.setEmail(email);
        newAccount.setPassword(password);
        newAccount.setAccounttype(accountType);

        newAccount.setDatecreation(new java.util.Date() );

        try{
            manager.persist(newAccount);
        } catch( EntityExistsException e ){

            System.out.println( e.getLocalizedMessage() );
            return null;
        }

        System.out.printf("Hello %s", newAccount.getUsername() );
        return newAccount;
    }

    public void refreshAccount(Account account){
        manager.refresh(account);
    }

    /**
     * Update account data.
     * 
     * @param account
     */
    public void updateAccount( Account account ){
        manager.merge(account);
    }

    /**
     * Create a new band.
     *
     * @param owner the account associated with de band.
     * @param name  the name of the band
     * @param dateFormation
     * @param description
     * @param biography
     *
     * @return the band created
     */
    public Band createBand(Account owner, String name, Date dateFormation,
                              String description, String biography) {

        Band newBand = new Band();

        newBand.setName(name);
        newBand.setFormed(dateFormation);
        newBand.setDescription(description);
        newBand.setBiography(biography);
        newBand.setDatecreation(new java.util.Date() );

        owner.setBand(newBand);
        newBand.setIdband( owner.getIdaccount() );
        newBand.setAccount(owner);

        manager.persist(newBand);

        return newBand;
    }

    /**
     * Update band data.
     * 
     * @param band
     */
    public void updateBand(Band band){
        manager.merge(band);
    }

    /**
     * Ask for a new password to be sent by email.
     *
     * TODO: implement mail send.
     * 
     * @param email the recipient email.
     */
    public void requestNewPassword(String email) {

        // email is unique, so we can find it
        Account searchAccount;

        Query q = manager.createQuery("from Account a where a.email = :email");
        searchAccount = (Account) q.setParameter("email", email).getSingleResult();

        // TODO : if Account not null, send email..
    }

    /**
     * Get a list of all accounts.
     *
     * @return a list with all accounts in the system.
     */
    public List<Account> findAllAccounts() {
        return manager.createQuery("select object(o) from Account as o").getResultList();
    }

    /**
     * Find a specific account by its name.
     *
     * @param name the name of the account to search for.
     * @return the Account object.
     * @throws AccountDoesNotExist when the with username <code>name</name>
     * does not exist.
     */
    public Account findAccount(String name) throws AccountDoesNotExist {
        Query q = manager.createQuery("SELECT a FROM Account a WHERE a.username = :username");
        q.setParameter("username", name);

        try{
            Account acc = (Account) q.getSingleResult();
            return acc;
        } catch( NoResultException e ){
            throw new AccountDoesNotExist( name );
        }

    }

    /**
     * Find all bands with a specific name.
     *
     * @param name the name of the band to search for.
     * @return a list with all bands that match <code>name</code>
     * 
     * @throws AccountDoesNotExist when no bands are found.
     */
    public List<Band> findBands(String name) throws AccountDoesNotExist {
        Query q = manager.createQuery("SELECT b FROM Band b WHERE b.name = :name");
        q.setParameter("name", name);

        try{
            List<Band> bands = q.getResultList();
            return bands;
        } catch( NoResultException e ){
            throw new AccountDoesNotExist( name );
        }
    }

    /**
     * Find a band by its ID.
     *
     * @param IDBand
     * @return the Band object.
     * @throws AccountDoesNotExist when the band is not found.
     */
    public Band findBand(Integer IDBand) throws AccountDoesNotExist {
        Query q = manager.createQuery("SELECT b FROM Band b WHERE b.idband = :idband");
        q.setParameter("idband", IDBand);

        try{
            Band band = (Band) q.getSingleResult();
            return band;
        } catch( NoResultException e ){
            throw new AccountDoesNotExist( "Band :" + IDBand.toString() );
        }
    }

}
